package com.hzw.saas.service.template.service;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hzw.saas.api.template.IBusinessTemplateHandler;
import com.hzw.saas.api.template.ITemplateService;
import com.hzw.saas.api.template.bo.TemplateBO;
import com.hzw.saas.api.template.bo.TemplateTypeBO;
import com.hzw.saas.api.template.bo.TemplateTypeKeyBO;
import com.hzw.saas.api.template.enums.TemplateTypeEnum;
import com.hzw.saas.api.template.enums.TemplateTypeKeyEnum;
import com.hzw.saas.api.template.query.TemplateAddQuery;
import com.hzw.saas.api.template.query.TemplateUpdateQuery;
import com.hzw.saas.common.config.util.AssertUtil;
import com.hzw.saas.common.config.util.MybatisPlusUtil;
import com.hzw.saas.common.config.util.SpringContextUtils;
import com.hzw.saas.common.util.MapperUtil;
import com.hzw.saas.common.util.SnowFlakeUtil;
import com.hzw.saas.common.util.StringUtils;
import com.hzw.saas.service.template.mapper.TemplateMapper;
import com.hzw.saas.service.template.model.Template;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import org.springframework.stereotype.Service;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * @author zzl
 * @since 09/07/2021
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class TemplateServiceImpl extends ServiceImpl<TemplateMapper, Template> implements ITemplateService, IService<Template> {

    @Override
    public TemplateBO convertTemplate(String pid, String... bizParams) {
        Template template = super.getById(pid);
        Assert.notNull(template, "模板不存在: {}", pid);
        return this.convertTemplate(template, bizParams);
    }

    @Override
    public TemplateBO convertTemplate(Integer type, String... bizParams) {
        LambdaQueryChainWrapper<Template> query = super.lambdaQuery()
            .eq(Template::getType, type)
            .orderByDesc(Template::getCreateTime);
        MybatisPlusUtil.limitOne(query);
        Template template = query.one();
        Assert.notNull(template, "模板不存在: {}", type);
        return this.convertTemplate(template, bizParams);
    }

    public TemplateBO convertTemplate(Template template, String... bizParams) {
        TemplateBO bo = MapperUtil.nf().map(template, TemplateBO.class);
        if (StrUtil.isBlank(template.getAction())) {
            return bo;
        }
        IBusinessTemplateHandler handler = SpringContextUtils.getBean(bo.getAction(), IBusinessTemplateHandler.class);
        return handler.handle(bo, bizParams);
    }

    @Override
    public List<TemplateTypeBO> listTemplateTypes() {
        List<TemplateTypeBO> result = new ArrayList<>();
        for (TemplateTypeEnum value : TemplateTypeEnum.values()) {
            TemplateTypeBO typeBO = MapperUtil.nf().map(value, TemplateTypeBO.class);
            List<TemplateTypeKeyEnum> keys = TemplateTypeKeyEnum.listInstance(value.getType());
            List<TemplateTypeKeyBO> keysBO = MapperUtil.nf().mapAsList(keys, TemplateTypeKeyBO.class);
            typeBO.setKeys(keysBO);
            result.add(typeBO);
        }
        return result;
    }

    @Override
    public TemplateTypeBO getTemplateType(Integer type) {
        TemplateTypeEnum instance = TemplateTypeEnum.instance(type);
        if (Objects.isNull(instance))
            return null;
        TemplateTypeBO typeBO = MapperUtil.nf().map(instance, TemplateTypeBO.class);
        List<TemplateTypeKeyEnum> keys = TemplateTypeKeyEnum.listInstance(instance.getType());
        List<TemplateTypeKeyBO> keysBO = MapperUtil.nf().mapAsList(keys, TemplateTypeKeyBO.class);
        typeBO.setKeys(keysBO);
        return typeBO;
    }

    @Override
    public List<TemplateBO> listTemplates(Integer type, String key) {
        List<Template> list = super.lambdaQuery()
            .eq(Objects.nonNull(type), Template::getType, type)
            .eq(StrUtil.isNotBlank(key), Template::getKey, key)
            .orderByDesc(Template::getCreateTime)
            .list();
        return MapperUtil.nf().mapAsList(list, TemplateBO.class);
    }

    @Override
    public TemplateBO getTemplate(String pid) {
        Template template = super.getById(pid);
        return MapperUtil.nf().map(template, TemplateBO.class);
    }

    @Override
    public TemplateBO addTemplate(TemplateAddQuery query) {
        // 校验参数
        AssertUtil.assertThrow("模板名称为空", StrUtil.isBlank(query.getName()));
        TemplateTypeEnum.assertValid(query.getType());
        // 初始化
        Template template = MapperUtil.nf().map(query, Template.class);
        template.setPid(SnowFlakeUtil.nextIdStr());
        super.save(template);
        return MapperUtil.nf().map(template, TemplateBO.class);
    }

    @Override
    public boolean updateTemplate(TemplateUpdateQuery query) {
        // 校验参数
        AssertUtil.assertThrow("pid为空", StrUtil.isBlank(query.getPid()));
        AssertUtil.assertThrow("模板名称为空", StringUtils.isBlankText(query.getName()));
        if (Objects.nonNull(query.getType())) {
            TemplateTypeEnum.assertValid(query.getType());
        }
        Template template = MapperUtil.nf().map(query, Template.class);
        return super.updateById(template);
    }

    @Override
    public boolean deleteTemplate(String... pids) {
        if (ArrayUtil.isEmpty(pids))
            return true;
        return super.removeByIds(ListUtil.toList(pids));
    }
}
